﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using AWS.SLAM.Activation;
using AWS.SLAM.Configuration;
using AWS.SLAM.Hierarchy.Data;
using AWS.SLAM.Logging;
using AWS.SLAM.StructureMap;
using AWS.SLAM.SharePoint;
using Microsoft.SharePoint;

namespace AWS.SLAM.Hierarchy
{
    public class HierarchyDataSynchronizeTypeProcessor : IDataSynchronizeTypeProcessor
    {
        #region Private State

        private IConfigurationManager _configuration;
        private ILogger _logger;

        #endregion

        #region Constructors

        public HierarchyDataSynchronizeTypeProcessor(IConfigurationManager configuration, ILogger logger)
        {   
            _configuration = configuration;
            _logger = logger;
        }

        #endregion

        #region IDataSynchronizeTypeProcessor Members

        public void Process(string sharepointSiteLocation, IDictionary<string, object> parameters)
        {
            if (parameters["ConfigType"] is ConfiguredType)
            {
                ConfiguredType inputType = (ConfiguredType)parameters["ConfigType"];

                if (parameters.ContainsKey("PopulateData") && (bool)parameters["PopulateData"])
                {
                    //If this is a hierarchical type, update every list item that this type
                    //corresponds to so that they have the "s", or "stay" flag set instead of
                    //"m" or "a" on the hierarchy list field before these items get processed
                    using (SPSite outerSiteCollection = new SPSite(sharepointSiteLocation))
                    {
                        SPWeb site = null;

                        try
                        {
                            site = outerSiteCollection.OpenWeb();
                        }
                        catch
                        {
                            //failed
                        }

                        if (site != null)
                        {
                            SPSecurity.RunWithElevatedPrivileges(delegate()
                            {
                                using (SPSite elevatedSite = new SPSite(site.Site.ID))
                                {
                                    SPWeb elevatedWeb = null;
                                    if (String.IsNullOrEmpty(inputType.Site))
                                    {
                                        elevatedWeb = elevatedSite.RootWeb;
                                    }
                                    else
                                    {
                                        elevatedWeb = elevatedSite.AllWebs[inputType.Site];
                                    }

                                    if (elevatedWeb != null && elevatedWeb.Exists)
                                    {
                                        if (inputType.ContentType)
                                        {
                                            SPContentType contentType = null;
                                            try
                                            {
                                                contentType = elevatedWeb.ContentTypes[inputType.Name];
                                            }
                                            catch
                                            {
                                                //failed
                                            }

                                            if (contentType != null)
                                            {
                                                try
                                                {
                                                    //To process a Content Type, iterate through
                                                    //all sites in the site collection, find each
                                                    //List that contains this Content Type and call
                                                    //IItemUpdater.Update on every item that is of this
                                                    //Content Type.
                                                    for (int i = 0; i < elevatedSite.AllWebs.Count; i++)
                                                    {
                                                        SPWeb subWeb = elevatedSite.AllWebs[i];
                                                        foreach (SPList list in subWeb.Lists)
                                                        {
                                                            if (list.ContentTypes.Contains(contentType))
                                                            {
                                                                foreach (SPListItem listItem in list.Items)
                                                                {
                                                                    //Check if this SPListItem is of the Content Type being processed,
                                                                    //if it matches call Update.
                                                                    if (listItem.ContentType != null && listItem.ContentType.EqualsOrInherits(inputType.Name))
                                                                    {
                                                                        listItem.HoldHierarchyPositionFieldValue();
                                                                    }
                                                                }
                                                            }
                                                        }
                                                        subWeb.Dispose();
                                                    }
                                                }
                                                catch(Exception ex)
                                                {
                                                    _logger.LogMessage("Exception", ex.ToString());
                                                }
                                            }
                                        }
                                        else
                                        {
                                            try
                                            {
                                                SPList list = null;

                                                //If ID is present, try to open the List by ID otherwise just
                                                //let it fail...
                                                if (!String.IsNullOrEmpty(inputType.Id))
                                                {
                                                    list = elevatedWeb.Lists[new Guid(inputType.Id)];
                                                }
                                                else
                                                {
                                                    list = elevatedWeb.Lists[inputType.Name];
                                                }

                                                if (list != null)
                                                {
                                                    //Call update for every item in the list
                                                    foreach (SPListItem listItem in list.Items)
                                                    {
                                                        listItem.HoldHierarchyPositionFieldValue();
                                                    }
                                                }
                                            }
                                            catch
                                            {
                                                //Fails to here if list is not found...
                                            }
                                        }
                                        elevatedWeb.Dispose();
                                    }
                                }
                            });

                            site.Dispose();
                        }
                    }
                }
            }
            SqlDataSynchronizeTypeProcessor subProcessor = new SqlDataSynchronizeTypeProcessor(_configuration, _logger);
            subProcessor.Process(sharepointSiteLocation, parameters);
        }

        #endregion
    }
}
